#include "login_win.h"
#include <QLineEdit>
#include <QErrorMessage>
#include <QString>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include "watcher.h"
#include "reg_win.h"
#include "g_headers.h"
#include "sync_win.h"
#include <pthread.h>
#include <QPicture>
#include <QBitmap>
#include <QPalette>
#include <QPixmap>
#include <QMouseEvent>
#include <iostream>
#include <arpa/inet.h>
using namespace std;

QPushButton *custButton(QString str,QString str1)
{
    QPushButton *pushButton= new QPushButton;

    pushButton->setGeometry(10,10,200,200); //按钮的位置及大小
    pushButton->clearMask();
    pushButton->setBackgroundRole( QPalette::Base);

    QPixmap mypixmap;   mypixmap.load(str);

    pushButton->setFixedSize( mypixmap.width(), mypixmap.height() );
    pushButton->setMask(mypixmap.createHeuristicMask());
    pushButton->setIcon(mypixmap);
    pushButton->setIconSize(QSize(mypixmap.width(),mypixmap.height()));
    pushButton->setToolTip(str1);
    return pushButton;
}

Login_win::Login_win(Watcher *ptr, bool &p_update, QMainWindow* parent)
    : update(p_update), QMainWindow(parent)
{
    //隐藏窗口边框
    this->setWindowFlags(Qt::FramelessWindowHint);

    //窗体透明化
    this->setAttribute(Qt::WA_TranslucentBackground, true);
    this->setWindowOpacity(0.9);

    //初始化窗体
    this->setupUi(this);

    //设置两个按钮透明
    login_button->setFlat(true);
    reg_button->setFlat(true);

    //自定义登录按钮的样式
//    QPixmap mypixmap;
//    mypixmap.load("../ui/button.png");
//    login_button->setGeometry(10,80,80,25);
//    login_button->clearMask();
//    login_button->setBackgroundRole( QPalette::Base);
//    login_button->setFixedSize( mypixmap.width(), mypixmap.height() );
//    login_button->setMask(mypixmap.createHeuristicMask());
//    login_button->setIcon(mypixmap);
//    login_button->setIconSize(QSize(mypixmap.width(), mypixmap.height()));
//    login_button->setToolTip("login");

    //设置密码输入框的回显
    pwd_input->setEchoMode(QLineEdit::Password);

    gsyncer = ptr;
    sync_win = new Sync_win(gsyncer,this->version,this->update);

    connect(this,SIGNAL(start_watch()),this,SLOT(login_succeed()));
}

void Login_win::mousePressEvent(QMouseEvent * event)
{
    if (event->button() == Qt::LeftButton) //点击左边鼠标
    {
         dragPosition = event->globalPos() - frameGeometry().topLeft();
         //globalPos()获取根窗口的相对路径，frameGeometry().topLeft()获取主窗口左上角的位置
         event->accept();   //鼠标事件被系统接收
    }
    if (event->button() == Qt::RightButton)
    {
         close();
    }
}

void Login_win::mouseMoveEvent(QMouseEvent * event)
{
    if (event->buttons() == Qt::LeftButton) //当满足鼠标左键被点击时。
    {
         move(event->globalPos() - dragPosition);//移动窗口
         event->accept();
    }
}

void Login_win::login_succeed()
{
    pthread_t tid_process, tid_input;

    //处理事件线程
    if( pthread_create(&tid_process,NULL,Login_win::process_thread,(void*)this) < 0 )
    {
        perror("pthread_create");
        exit(-1);
    }

    if( pthread_create(&tid_input,NULL,Login_win::watch_thread,(void*)this) < 0 )
    {
        perror("pthread_create");
        exit(-1);
    }

    //监控线程
    //gsyncer->watch(all_path);
    win_thread(tid_process);
}

void* Login_win::watch_thread(void* p)
{
    (((Login_win*)p)->gsyncer)->watch(((Login_win*)p)->all_path);

}

void Login_win::win_thread(pthread_t id)
{
    this -> hide();
    sync_win->set_id(id);
    //Sync_win sync_win( ((Login_win*)p) ->gsyncer);
    //sync_win.exec();
    sync_win->exec();
}

void* Login_win::process_thread(void *p)
{
    (((Login_win*)p) ->gsyncer)->process_events();
   // ((Watcher*)gsyncer)->process_events();
}

void Login_win::on_login_button_clicked()
{
    if (connect_server(gsyncer->ctl_sock,gsyncer->srv_ctl) < 0)
        return;

    QString q_usr = usr_input->text();
    QString q_pwd = pwd_input->text();
    string usr = q_usr.toStdString();
    string pwd = q_pwd.toStdString();

    get_home(main_dir,usr);

    //打包
    ctl_pkg_t info;
    info.type = LOGIN;
    strncpy(info.str.id.usr,usr.c_str(),USR_LEN);
    strncpy(info.str.id.pwd,pwd.c_str(),PWD_LEN);

    //发送给服务器
    if( writen(gsyncer->ctl_sock,&info,sizeof(ctl_pkg_t)) < 0 )
    {
        QErrorMessage err_msg(this);
        err_msg.setWindowTitle("Error:");
        err_msg.showMessage("Can't send user info to the server");
        err_msg.exec();

        ::close(gsyncer->ctl_sock);
        return;
    }

    //读取服务器的应答
    int8_t reply;
    if( readn(gsyncer->ctl_sock,&reply,sizeof(reply)) < 0 )
    {
        QErrorMessage err_msg(this);
        err_msg.setWindowTitle("Error:");
        err_msg.showMessage("Can't read from the server");
        err_msg.exec();

        ::close(gsyncer->ctl_sock);
        return;
    }

    //reply<0说明登录失败
    if (reply != 0)
    {
        QErrorMessage err_msg(this);
        err_msg.setWindowTitle("Error:");
        err_msg.showMessage("ID or password wrong!");
        err_msg.exec();

        ::close(gsyncer->ctl_sock);
        return;
    }

    all_path.push_back(main_dir);
    string version_path;
    //通过查看用户主目录是否存在判定用户是否在这台机器第一次登录
    struct stat dir_info;
    int local_version;
    int local_version_fd;
    if( stat(main_dir.c_str(), &dir_info) < 0 )
    {
        if( errno == ENOENT)
        {
            //若第一次登录  则创建主目录
            if(mkdir(main_dir.c_str(),0766) < 0)
            {
                QErrorMessage err_msg(this);
                err_msg.setWindowTitle("Error:");
                err_msg.showMessage("can't make usr dir");
                err_msg.exec();

                ::close(gsyncer->ctl_sock);
                return;
            }

            //创建version文件

            version_path = main_dir + "/.version";
            if(( local_version_fd = open(version_path.c_str(),O_WRONLY|O_CREAT,0766)) < 0)
            {
                QErrorMessage err_msg(this);
                err_msg.setWindowTitle("Error:");
                err_msg.showMessage("can't create version file");
                err_msg.exec();

                ::close(gsyncer->ctl_sock);
                return;
            }

            //初始化版本号
            local_version = 0;
            if( write(local_version_fd,&local_version,sizeof(int)) < 0 )
            {
                perror("write to version file");
                QErrorMessage err_msg(this);
                err_msg.setWindowTitle("Error:");
                err_msg.showMessage("write to version file");
                err_msg.exec();

                ::close(gsyncer->ctl_sock);
                return;
            }


        }
        else
        {
            QErrorMessage err_msg(this);
            err_msg.setWindowTitle("Error:");
            err_msg.showMessage("stat function failed");
            err_msg.exec();

            ::close(gsyncer->ctl_sock);
            return;
        }

    }
    else        //直接读取本地版本号
    {
        //int fd;
        version_path = main_dir + "/.version";
        if(( local_version_fd = open(version_path.c_str(),O_RDONLY)) < 0)
        {
            QErrorMessage err_msg(this);
            err_msg.setWindowTitle("Error:");
            err_msg.showMessage("can't create version file");
            err_msg.exec();

            ::close(gsyncer->ctl_sock);
            return;
        }

        if(read(local_version_fd ,&local_version,sizeof(int)) < 0 )
        {
            QErrorMessage err_msg(this);
            err_msg.setWindowTitle("Error:");
            err_msg.showMessage("read from version file");
            err_msg.exec();

            ::close(gsyncer->ctl_sock);
            return;
        }

        //::close(fd);
    }


//    if( chdir(main_dir.c_str()) < 0 )
//    {
//        perror("chdir");
//        QErrorMessage err_msg(this);
//        err_msg.setWindowTitle("Error:");
//        err_msg.showMessage("chdir to main_dir error!");
//        err_msg.exec();

//        ::close(gsyncer->ctl_sock);
//        return;
//    }



    //读取服务器端的版本号
    int real_version;
    if( readn(gsyncer->ctl_sock,&real_version,sizeof(int)) < 0 )
    {
        QErrorMessage err_msg(this);
        err_msg.setWindowTitle("Error:");
        err_msg.showMessage("Can't read real version");
        err_msg.exec();

        ::close(gsyncer->ctl_sock);
        return;
    }

    cout << local_version <<" " << real_version<< endl;
    //若本地版本号比服务器小  说明需要同步
    if(local_version < real_version)
    {
        int sync_fd = tcp_connect(SRV_IP,"1235");

        //发送请求号
        uint8_t request = DATA_SYNC;
        int res;

        if( (res = write(sync_fd,&request,sizeof(request))) <0 )
        {
            //cerr << "send request" << endl;
            perror("send request");
        }
        //cout << res << endl;

        //发送用户ID
        if((res=write(sync_fd,info.str.id.usr,USR_LEN)) <0 )
        {
            //cerr << "send id" << endl;
            perror("send id");
        }
        //cout << res << endl;
        //pause();

        //发送本地版本号
        if(write(sync_fd,&local_version,sizeof(int)) <0)
        {
            cout << local_version << endl;
            //cerr << "send local" << endl;
            perror("send local");
        }

        //发送服务器版本号
        if(write(sync_fd,&real_version,sizeof(int)) < 0)
        {
            cout << local_version << endl;
            //cerr << "send real" << endl;
            perror("send real");
        }

        //接收日志
        ctl_pkg_t logs;
        char prepath[USR_LEN];
        snprintf(prepath,USR_LEN,"/home/%s/gsyncer",cuserid(NULL));
        char path[PATH_LEN];

        while(true)
        {
            int res;
            if( (res =read(sync_fd,&logs,sizeof(logs))) <= 0 )
            {
                perror("read from sync-fd");
                ::close(sync_fd);
                break;
            }
            cout << res << endl;
            cout << logs.str.path << endl;
            //snprintf(path,PATH_LEN,"%s%s",prepath,logs.str.path);
            decode_path(logs.str.path,path);
            if(logs.type == CREATE)
            {
                //cout << "path" << endl;
                if(mkdir(path,0766) < 0 )
                    perror("mkdir");
            }
            else if ( logs.type == CREATE_F )
            {
                int fd = open(path,O_RDONLY|O_CREAT,0766);
                if( fd < 0 )
                    perror("creat");

                ::close(fd);
            }
            else if ( logs.type == DEL_F )
            {
                if( unlink(path) < 0 )
                    perror("unlink");
            }
            else if ( logs.type == DEL_D )
            {
                if( rmdir(path) < 0 )
                    perror("rmdir");
            }
            else if ( logs.type == UP_F )
            {
                pull_file(logs);
            }
            else if ( logs.type == UP_D )
            {

            }
        }
        //更新本地本地版本号
        ::close(local_version_fd);
        local_version_fd = open(version_path.c_str(),O_RDWR|O_TRUNC);

        if(write(local_version_fd,&real_version,sizeof(int)) < 0 )
            perror("write");
        ::close(local_version_fd);
        //file_rcv(fd_zip,gsyncer->ctl_sock);
    }



    //找出所有文件夹，存入all_path
    dir_search(all_path,main_dir);
    gsyncer->set_usr_info(usr,pwd);
    this->version = real_version;
    this->update = false;
    emit start_watch();

}

void Login_win::pull_file(ctl_pkg_t &log)
{
    int tsf_sock = tcp_connect(SRV_IP, "1235");
    if( tsf_sock < 0 )
        {
            perror("connect");
            exit(-1);
        }

    //发送PUSH请求
    uint8_t request = DATA_PULL;
    if( write(tsf_sock,&request,sizeof(uint8_t)) < 0 )
    {
        perror("send request to 1235");
        return;
    }

    //发送用户名
    char usr_name[USR_LEN];
    strncpy(usr_name,usr_input->text().toStdString().c_str(),USR_LEN);
    if( writen(tsf_sock,usr_name,USR_LEN) < 0)
    {
        perror("send usr_name to 1235");
        return;
    }

    //发送目录
   // snprintf(log.str.path, PATH_LEN, "%s%s", SRV_ROOT, temp_path + i);

    if(writen(tsf_sock,log.str.path,PATH_LEN) < 0 )
    {
        perror("send path to 1235");
        return;
    }

    char path[PATH_LEN];
    snprintf(path,PATH_LEN,"/home/%s/gsyncer%s",cuserid(NULL),log.str.path+strlen(SRV_ROOT));
    int fd_temp = open(path,O_WRONLY|O_TRUNC|O_CREAT);
    if( fd_temp < 0 )
    {
        cout<<"file "<<path<<" not exists now \n";
        return;

    }
    //Writen(tsf_sock,&head, sizeof(head));

    file_copy(fd_temp, tsf_sock);
    ::close(fd_temp);
    ::close(tsf_sock);

}

void Login_win::on_reg_button_clicked()
{
    Reg_Dialog reg_win(gsyncer);
    reg_win.exec();

}

void Login_win::decode_path(const char* from, char* to)
{
    int i = 0, counter = 0;
    for(; i < strlen(from) ; ++i)
    {
        if(from[i] == '/')
            counter++;
        if( counter == 2 )
            break;
    }

    sprintf(to,"/home/%s/gsyncer/%s",cuserid(NULL),from+i);
}

//int Login::connect_server()
//{
//    if( ( gsyncer.ctl_sock = socket(AF_INET,SOCK_STREAM,0)) < 0 )
//    {
//        QErrorMessage err_msg(this);
//        err_msg.setWindowTitle("Error:");
//        err_msg.showMessage("socket function failed");
//        err_msg.exec();

//        return -1;
//    }

//    if ( ::connect(gsyncer.ctl_sock,(struct sockaddr*)&gsyncer.srv_ctl,
//                            sizeof(gsyncer.srv_ctl)) < 0 )
//    {
//        QErrorMessage err_msg(this);
//        err_msg.setWindowTitle("Error:");
//        err_msg.showMessage("Can't connect to the server");
//        err_msg.exec();

//        return -1;
//    }

//    return 0;
//}
